package com.naiterui.ehp.bs.b2c.product.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.naiterui.common.repository.page.PageParamVO;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.bo.doctor.product.ProductInfoBO;
import com.naiterui.ehp.bp.bo.doctor.product.ProductSearchParamBO;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.lang.StringUtil;
import com.naiterui.ehp.bs.b2c.common.bo.inventory.StockBO;
import com.naiterui.ehp.bs.b2c.inventory.service.IStockService;
import com.naiterui.ehp.bs.b2c.product.entity.CommonDrug;
import com.naiterui.ehp.bs.b2c.product.entity.Medicine;
import com.naiterui.ehp.bs.b2c.product.entity.Product;
import com.naiterui.ehp.bs.b2c.product.entity.Sku;
import com.naiterui.ehp.bs.b2c.product.exception.ProductBusinessException;
import com.naiterui.ehp.bs.b2c.product.exception.ProductExceptionCodes;
import com.naiterui.ehp.bs.b2c.product.repository.ICommonDrugRepository;
import com.naiterui.ehp.bs.b2c.product.repository.IProductRepository;
import com.naiterui.ehp.bs.b2c.product.repository.ISkuRepository;
import com.naiterui.ehp.bs.b2c.product.service.ICommonDrugService;
import com.naiterui.ehp.bs.b2c.product.service.IProductService;
import com.naiterui.ehp.bs.b2c.product.service.ISkuImageService;
import com.naiterui.ehp.bs.b2c.product.vo.ProductInfoVO;

import cn.hutool.core.collection.CollUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 医生常用药
 * 
 * @author yangfuya
 * @since 2022/3/29
 */
@Slf4j
@Service
@AllArgsConstructor
public class CommonDrugServiceImpl implements ICommonDrugService {
    private final ICommonDrugRepository commonDrugRepository;
    private final IProductRepository productRepository;
    private final ISkuRepository skuRepository;
    private final IProductService productService;
    private final ISkuImageService skuImageService;
    private final IStockService stockService;

    @Override
    public PageVO<ProductInfoBO> list(ProductSearchParamBO productSearch) {
        return this.commonDrugPage(productSearch, 1);
    }

    @Override
    public PageVO<ProductInfoBO> useList(ProductSearchParamBO productSearch) {
        return this.commonDrugPage(productSearch, 0);
    }

    @Override
    public void addCommonDrug(Long doctorId, Long productId) throws BusinessException {
        this.checkProduct(productId);
        CommonDrug commonDrug = commonDrugRepository.findCommonDrugByDoctorIdAndProductId(doctorId, productId);
        if (commonDrug != null) {
            throw new ProductBusinessException(ProductExceptionCodes.PRODUCT_COMMON_DRUG_ADDED);
        }
        commonDrugRepository.save(CommonDrug.builder().doctorId(doctorId).productId(productId).createdAt(new Date())
            .createdBy(doctorId.toString()).build());
    }

    @Override
    public void removeCommonDrug(Long doctorId, Long productId) throws BusinessException {
        this.checkProduct(productId);
        CommonDrug commonDrug = commonDrugRepository.findCommonDrugByDoctorIdAndProductId(doctorId, productId);
        if (commonDrug == null) {
            throw new ProductBusinessException(ProductExceptionCodes.PRODUCT_COMMON_DRUG_NOT_ADDED);
        }
        commonDrugRepository.removeById(commonDrug.getId());
    }

    private PageVO<ProductInfoBO> commonDrugPage(ProductSearchParamBO productSearch, int type) {
        // 查询常用药分页数据
        PageParamVO pageParamVO = new PageParamVO(productSearch.getPage(), productSearch.getNum());
        Page<Sku> page;
        // 全部常用药
        if (type == 1) {
            page = skuRepository.findSkuByDoctorIdPageable(productSearch.getDoctorId(), pageParamVO.getPageable());
        }
        // 不包含已下架的常用药
        else {
            page = skuRepository.findSkuByStatusAndDoctorIdPageable(Sku.STATUS_UP, productSearch.getDoctorId(),
                pageParamVO.getPageable());
        }
        List<Sku> skuList = page.getContent();
        if (CollUtil.isEmpty(skuList)) {
            return PageVO.newBuilder().pageNo(pageParamVO.getPage()).pageSize(pageParamVO.getNum())
                .totalCount((int)page.getTotalElements()).result(Lists.newArrayList()).build();
        }
        Set<String> numbers = new HashSet<>();
        // 涉及pid
        Set<Long> pIds = new HashSet<>();
        Optional.ofNullable(skuList).ifPresent(s -> s.forEach(sku -> {
            pIds.add(sku.getProductId());
            numbers.add(sku.getNumber());
        }));
        Map<Long, Medicine> medicineMap = this.productService.getMapToMedicine(pIds);
        List<ProductInfoVO> result = new ArrayList<>();
        Optional.ofNullable(skuList).ifPresent(s -> s.forEach(sku -> {
            Medicine medicine = medicineMap.get(sku.getProductId());
            ProductInfoVO productInfoVO = ProductInfoVO.builder().productId(sku.getProductId()).skuId(sku.getId())
                .number(sku.getNumber())
                .name(
                    sku.getName().contains("null") ? sku.getName().replaceAll("null", "").trim() : sku.getName().trim())
                .icon(this.skuImageService.getSkuIcon(sku.getId())).rx(medicine.getNmpaType())
                .salePrice(sku.getSalePrice()).company(medicine.getProductionEnterprise()).status(sku.getStatus())
                .spec(medicine.getSpecification()).usage(medicine.getUsageDosage())
                .inventoryWarningValue(sku.getInventoryWarningValue()).build();
            result.add(productInfoVO);
        }));

        // 商品库存
        List<StockBO> stocks =
            stockService.getStocks(result.stream().map(ProductInfoVO::getSkuId).collect(Collectors.toSet()));

        Map<Long, Long> stockNumber =
            stocks.stream().collect(Collectors.toMap(StockBO::getSkuId, StockBO::getRemainQuantity, Long::sum));
        // 组装BO
        List<ProductInfoBO> productList = new ArrayList<>();
        result.forEach(productInfoVO -> {
            ProductInfoBO productInfoBO = new ProductInfoBO();
            BeanUtils.copyProperties(productInfoVO, productInfoBO);
            productInfoBO.setSalePrice(StringUtil.formatFen2YuanStr(productInfoVO.getSalePrice()));
            Long number = stockNumber.get(productInfoVO.getSkuId());
            productInfoBO.setQuantity(number == null ? 0L : number);
            productInfoBO.setCommonDrug(1);
            // 组装BO
            productList.add(productInfoBO);
        });
        return PageVO.newBuilder().pageNo(pageParamVO.getPage()).pageSize(pageParamVO.getNum()).result(productList)
            .totalCount((int)page.getTotalElements()).build();
    }

    private void checkProduct(Long productId) throws BusinessException {
        Product product = productRepository.get(productId);
        if (product == null) {
            throw new ProductBusinessException(ProductExceptionCodes.PRODUCT_NOT_FOUND);
        }

    }
}
